// modbusslave.cpp
#include "modbusslave.h"
#include <QSerialPort>
#include <QDebug>
#include <QThread>

modbusSlave::modbusSlave(ModbusType type, int maxRegisterAddress, QObject *parent)
    : QObject(parent), m_type(type), m_modbusServer(nullptr), m_slaveId(1),
      m_baudRate(9600), m_parity("None"), m_dataBits(8), m_stopBits(1), m_port(502),
      m_maxAddress(qMax(maxRegisterAddress, 100)) // 确保至少有100个寄存器
{
}

modbusSlave::~modbusSlave()
{
    stop();
}

void modbusSlave::setRTUConnectionParameters(const QString &portName, int baudRate,
                                             const QString &parity, int dataBits,
                                             int stopBits)
{
    m_portName = portName;
    m_baudRate = baudRate;
    m_parity = parity;
    m_dataBits = dataBits;
    m_stopBits = stopBits;
}

void modbusSlave::setTCPConnectionParameters(const QString &address, int port)
{
    m_address = address;
    m_port = port;
}

void modbusSlave::setSlaveId(int slaveId)
{
    m_slaveId = slaveId;
}

bool modbusSlave::start()
{
    qDebug() << "=== Starting Modbus Server ===";
    qDebug() << "Type:" << (m_type == TCP ? "TCP" : "RTU");
    qDebug() << "Slave ID:" << m_slaveId;
    qDebug() << "Port:" << m_port;
    qDebug() << "Address:" << m_address;
    qDebug() << "Max register address:" << m_maxAddress;

    if (m_modbusServer)
    {
        delete m_modbusServer;
        m_modbusServer = nullptr;
    }

    if (m_type == TCP)
    {
        m_modbusServer = new QModbusTcpServer(this);
        m_modbusServer->setConnectionParameter(QModbusServer::NetworkPortParameter, m_port);
        m_modbusServer->setConnectionParameter(QModbusServer::NetworkAddressParameter, m_address);
        qDebug() << "Created QModbusTcpServer";
    }
    else
    {
        m_modbusServer = new QModbusRtuSerialSlave(this);
        m_modbusServer->setConnectionParameter(QModbusServer::SerialPortNameParameter, m_portName);
        m_modbusServer->setConnectionParameter(QModbusServer::SerialBaudRateParameter, m_baudRate);
        m_modbusServer->setConnectionParameter(QModbusServer::SerialDataBitsParameter, m_dataBits);
        m_modbusServer->setConnectionParameter(QModbusServer::SerialStopBitsParameter, m_stopBits);

        QSerialPort::Parity parity = QSerialPort::NoParity;
        if (m_parity == "Even")
            parity = QSerialPort::EvenParity;
        else if (m_parity == "Odd")
            parity = QSerialPort::OddParity;
        m_modbusServer->setConnectionParameter(QModbusServer::SerialParityParameter, parity);
        qDebug() << "Created QModbusRtuSerialSlave";
    }

    // 设置从机地址
    m_modbusServer->setServerAddress(m_slaveId);
    qDebug() << "Set server address to:" << m_slaveId;

    setupConnections();

    bool result = m_modbusServer->connectDevice();
    qDebug() << "Connect device result:" << result;

    if (result)
    {
        // 等待连接建立
        QThread::msleep(100);

        // 根据预设的最大地址初始化寄存器范围
        qDebug() << "Initializing register ranges with max address:" << m_maxAddress;

        // 为保持寄存器设置范围
        QModbusDataUnit holdingRegisters;
        holdingRegisters.setRegisterType(QModbusDataUnit::HoldingRegisters);
        holdingRegisters.setStartAddress(0);
        holdingRegisters.setValueCount(m_maxAddress + 1); // 使用预设的最大地址

        // 使用QVector而不是QList以兼容Qt新版本
        QVector<quint16> initialValues(m_maxAddress + 1, 0);
        holdingRegisters.setValues(initialValues);

        // 创建QModbusDataUnitMap以兼容新版本Qt
        QModbusDataUnitMap regMap;
        regMap.insert(QModbusDataUnit::HoldingRegisters, holdingRegisters);

        if (m_modbusServer->setMap(regMap))
        {
            qDebug() << "Successfully initialized holding registers range 0-" << m_maxAddress;
        }
        else
        {
            qDebug() << "Failed to initialize holding registers range";
        }
    }

    return result;
}

void modbusSlave::stop()
{
    if (m_modbusServer)
    {
        m_modbusServer->disconnectDevice();
        delete m_modbusServer;
        m_modbusServer = nullptr;
    }
}

void modbusSlave::setDataMap(const QMap<int, QVariant> &dataMap)
{
    m_dataMap = dataMap;
    // qDebug() << "=== setDataMap called ===";
    // qDebug() << "Data map size:" << dataMap.size();

    // 如果服务器正在运行，需要将数据设置到Modbus寄存器中
    if (m_modbusServer)
    {
        int setCount = 0;
        // 遍历数据映射表，将数据设置到对应的寄存器中
        for (auto it = dataMap.begin(); it != dataMap.end(); ++it)
        {
            int address = it.key();
            QString valueStr = it.value().toString();

            // qDebug() << "Processing address:" << address << "value:" << valueStr;

            // 检查地址是否在有效范围内
            if (address >= 1 && address <= m_maxAddress)
            {
                quint16 registerValue = 0;

                // 检查是否为空值
                if (valueStr != "--" && !valueStr.isEmpty())
                {
                    // 转换为double然后乘以100转为16位整数
                    bool ok;
                    double doubleValue = valueStr.toDouble(&ok);
                    if (ok)
                    {
                        // 按原数据*100来存储
                        registerValue = static_cast<quint16>(doubleValue * 100);
                    }
                }

                // qDebug() << "Setting register at internal index:" << address
                //  << "with raw value:" << (registerValue / 100.0) // 显示原始值
                //  << "stored as:" << registerValue;               // 显示存储值

                // 用户地址1-9999直接映射到保持寄存器1-9999
                bool setResult = m_modbusServer->setData(QModbusDataUnit::HoldingRegisters, address, registerValue);
                if (setResult)
                {
                    setCount++;
                    // qDebug() << "Successfully set register at index" << address;
                }
                else
                {
                    qDebug() << "Failed to set register at index" << address;
                }
            }
            else
            {
                qDebug() << "Address" << address << "out of valid range (1-" << m_maxAddress << ")";
            }
        }
        // qDebug() << "Set" << setCount << "registers successfully";
    }
    else
    {
        qDebug() << "Modbus server not initialized";
    }
    // qDebug() << "=== setDataMap completed ===";
}

QMap<int, QVariant> modbusSlave::getDataMap() const
{
    return m_dataMap;
}

void modbusSlave::printServerInfo() const
{
    if (m_modbusServer)
    {
        qDebug() << "=== Modbus Server Info ===";
        qDebug() << "Server Address (Slave ID):" << m_modbusServer->serverAddress();
        qDebug() << "Server State:" << m_modbusServer->state();
        qDebug() << "========================";
    }
    else
    {
        qDebug() << "Modbus server not initialized";
    }
}

bool modbusSlave::testRegisterAccess(int address) const
{
    if (!m_modbusServer)
        return false;

    quint16 value = 0;
    bool result = m_modbusServer->data(QModbusDataUnit::HoldingRegisters, address, &value);
    qDebug() << "Testing register access at index" << address << "result:" << result << "value:" << value;
    return result;
}

void modbusSlave::handleDataWritten(QModbusDataUnit::RegisterType table, int address, int size)
{
    // qDebug() << "Data written to register type:" << table << "address:" << address << "size:" << size;
}

void modbusSlave::handleErrorOccurred(QModbusDevice::Error error)
{
    QString errorString;
    switch (error)
    {
    case QModbusDevice::NoError:
        errorString = "No error";
        break;
    case QModbusDevice::ReadError:
        errorString = "Read error";
        break;
    case QModbusDevice::WriteError:
        errorString = "Write error";
        break;
    case QModbusDevice::ConnectionError:
        errorString = "Connection error";
        break;
    case QModbusDevice::ConfigurationError:
        errorString = "Configuration error";
        break;
    case QModbusDevice::TimeoutError:
        errorString = "Timeout error";
        break;
    case QModbusDevice::ProtocolError:
        errorString = "Protocol error";
        break;
    case QModbusDevice::ReplyAbortedError:
        errorString = "Reply aborted error";
        break;
    case QModbusDevice::UnknownError:
        errorString = "Unknown error";
        break;
    default:
        errorString = "Undefined error";
        break;
    }

    qDebug() << "===============Modbus error occurred:=============" << errorString;
    emit errorOccurred(errorString);
}

void modbusSlave::handleStateChanged(QModbusDevice::State state)
{
    QString stateString;
    switch (state)
    {
    case QModbusDevice::UnconnectedState:
        stateString = "Unconnected";
        break;
    case QModbusDevice::ConnectingState:
        stateString = "Connecting";
        break;
    case QModbusDevice::ConnectedState:
        stateString = "Connected";
        break;
    case QModbusDevice::ClosingState:
        stateString = "Closing";
        break;
    default:
        stateString = "Undefined";
        break;
    }

    qDebug() << "================Modbus state changed:===============" << stateString;
}

void modbusSlave::setupConnections()
{
    if (!m_modbusServer)
        return;

    // 正确连接信号和槽
    connect(m_modbusServer, &QModbusServer::dataWritten,
            this, &modbusSlave::handleDataWritten);

    connect(m_modbusServer, &QModbusServer::errorOccurred,
            this, &modbusSlave::handleErrorOccurred);

    connect(m_modbusServer, &QModbusServer::stateChanged,
            this, &modbusSlave::handleStateChanged);
}